package com.isesol.seckill.service.impl;

import com.isesol.arch.common.uitil.redis.*;
import com.isesol.seckill.*;
import com.isesol.seckill.enums.*;
import com.isesol.seckill.result.*;
import com.isesol.seckill.service.*;
import org.apache.commons.lang3.*;
import org.slf4j.*;
import org.springframework.stereotype.*;

import javax.annotation.*;

/**
 * 秒杀逻辑 Service实现
 *
 * @author Peter Zhang
 */
@Service("secKillService")
public class SecKillServiceImpl implements SecKillService {

    protected Logger LOGGER = LoggerFactory.getLogger(getClass());

    /**
     * RedisUtil
     */
    @Resource
    RedisUtil redisUtil;

    /**
     * 秒杀数据服务
     */
    @Resource
    CountService countService;

    /**
     * 组装失败返回
     *
     * @param errorCode
     * @param errorMessage
     * @return
     */
    private Result<SecKillResult> assembleFailResult(ErrorCode errorCode, String errorMessage) {

        Result<SecKillResult> result = new Result<>();

        result.setSuccess(false);
        result.setErrorCode(errorCode);
        result.setErrorMessage(errorMessage);

        return result;
    }

    /**
     * 组装成功返回
     *
     * @param returnURL
     * @return
     */
    private Result<SecKillResult> assembleSuccessResult(String returnURL) {

        Result<SecKillResult> result = new Result<>();

        SecKillResult secKillResult = new SecKillResult();
        secKillResult.setReturnURL(returnURL);

        result.setSuccess(true);
        result.setModel(secKillResult);

        return result;
    }

    private boolean validateParams(String code, String id, String captchaId, String answer, String token) {

        boolean result=true;

        if (StringUtils.isEmpty(code)) {

            LOGGER.warn("seckill params error,code is null");

            result = false;
        }

        if (StringUtils.isEmpty(id)) {

            LOGGER.warn("seckill params error,id is null");

            result = false;
        }

        if (StringUtils.isEmpty(captchaId)) {

            LOGGER.warn("seckill params error,captchaId is null");

            result = false;
        }

        if (StringUtils.isEmpty(answer)) {

            LOGGER.warn("seckill params error,answer is null");

            result = false;
        }

        if (StringUtils.isEmpty(token)) {

            LOGGER.warn("seckill params error,token null");

            result = false;
        }

        return result;
    }

    @Override
    public void setSecKillStatus(String code, String id, SecKillStatusEnum secKillStatusEnum) throws Exception {

        String key=code+":"+id;

        SecKillStatusInfo.SEC_KILL_STATUS_MAP.put(key,SecKillStatusEnum.NORMAL);

    }

    @Override
    public Result<SecKillResult> secKill(String code, String id, String captchaId, String answer, String token)
            throws Exception {

        try {

            /**
             * 参数校验
             */
            if(!validateParams(code,id,captchaId,answer,token)){

                return assembleFailResult(
                        ErrorCode.PARAMETER_VALID_NOT_PASS, ErrorCode.PARAMETER_VALID_NOT_PASS.getMessage());
            }

            // 拼验证码 key
            String captchaKey = "captcha:" + code + ":" + id + "-" + captchaId + ":ans";
            String captchaItem = "captcha:" + code + ":" + id + "-" + captchaId;
            String rightAnswer = redisUtil.get(captchaKey);

            if (validateCaptcha(code, id, captchaId, answer, rightAnswer)) {

                return assembleFailResult(
                        ErrorCode.INVALID_CAPTCHA_ANSWER, ErrorCode.INVALID_CAPTCHA_ANSWER.getMessage());
            }

            String secKillKey=code+":"+id;

            long memStock=countService.getStockInfo(secKillKey);

            if(memStock>0){

                long realStock=redisUtil.decr("stock:"+secKillKey);

                LOGGER.info("seckill secKillKey={}.实际库存={}",secKillKey,realStock);

                // 减本地内存库存
                if(realStock>=0){

                    countService.setStockInfo(secKillKey,realStock);

                    countService.incSalesInfo(secKillKey);

                    //清除本次验证码
                    redisUtil.del(captchaKey);
                    redisUtil.del(captchaItem);

                    return assembleSuccessResult("http://www.baidu.com?"+realStock);

                }else{

                    countService.setStockInfo(secKillKey,0);

                    return assembleFailResult(
                            ErrorCode.SEC_KILL_FAIL, ErrorCode.SEC_KILL_FAIL.getMessage());
                }

            }else{

                return assembleFailResult(
                        ErrorCode.SEC_KILL_FAIL, ErrorCode.SEC_KILL_FAIL.getMessage());

            }

        } catch (Exception e) {

            LOGGER.warn("seckill error",e);

            throw e;
        }
    }

    private boolean validateCaptcha(String code, String id, String captchaId, String answer, String rightAnswer) {

        if (StringUtils.isEmpty(rightAnswer)) {

            LOGGER.error("seckill answer error, " +
                            "code={},id={},captchaId={},answer={}",
                    new Object[]{code, id, captchaId, answer});

            return true;
        }

        if (!StringUtils.equals(rightAnswer, answer)) {

            LOGGER.error("seckill error answer, " +
                            "code={},id={},captchaId={},rightAnswer={},answer={}",
                    new Object[]{code, id, captchaId, rightAnswer, answer});
            return true;

        }
        return false;
    }
}
